<script setup>
import { ref, onMounted, inject } from 'vue';
import { ElMessage } from 'element-plus';
import { useRoute, useRouter } from 'vue-router';
import { BREADCRUMBS, APP_CODE } from '@/plugins/global';
import { cloneDeep } from 'lodash';

const axios = inject('axios'), route = useRoute(), router = useRouter();

// ---- 初始化。
const roleCode = route.params.roleCode;
const authorityTree = ref([]);
onMounted(async () => {
  if (roleCode) {
    BREADCRUMBS.splice(0, BREADCRUMBS.length,
      { label: '角色列表', path: '/home/role_list' },
      { label: '角色详情', path: '/home/role_upsert' }
    );
    await authorityTreeGet();
    await authorityTreeDisable(authorityTree.value, true);
    roleGet();
  } else {
    BREADCRUMBS.splice(0, BREADCRUMBS.length,
      { label: '角色列表', path: '/home/role_list' },
      { label: '角色插入', path: '/home/role_upsert' }
    );
    authorityTreeGet();
  }
});

// ---- 权限树获取。
const authorityTreeProps = {
  "label": "name",
  "children": "children",
}
const authorityTreeGet = async () => {
  const response = await axios.get('/api/cms-web/authority/get/tree');
  if (response.data.success) {
    if (response.data.data) {
      authorityTree.value = response.data.data.children;
    }
  } else {
    ElMessage.error(response.data.message);
  }
}

// ---- 权限树禁用。
const authorityTreeRef = ref(null);
const authorityTreeDisable = async (authorities, disabled) => {
  for (let authority of authorities) {
    const authorityNode = authorityTreeRef.value.getNode(authority.authorityCode);
    authorityNode.data.disabled = disabled;
    authorityTreeDisable(authority.children, disabled);
  }
}

// ---- 角色获取。
const authorityMap = ref({})
const roleUpsert = ref({
  "roleCode": null,
  "name": null,
  "authorities": []
});
const roleGet = () => {
  axios.get(`/api/cms-web/role/get?roleCode=${roleCode}`).then(response => {
    if (response.data.success) {
      // ---- 角色数据。
      const data = response.data.data;
      roleUpsert.value.roleCode = data.roleCode;
      roleUpsert.value.name = data.name;
      // ---- 权限数据。
      if (data.authorities && data.authorities.length > 0) {
        const authorityCodes = [];
        for (let authority of data.authorities) {
          authorityCodes.push(authority.authorityCode);
          authorityMap.value[authority.authorityCode] = authority.expireDatetimeStr;
        }
        authorityTreeRef.value.setCheckedKeys(authorityCodes);
      }
    } else {
      ElMessage.error(response.data.message);
    }
  });
}

// ---- 权限是否选中。
const authorityIsCheck = (authorityCode) => {
  return authorityTreeRef.value.getCheckedKeys(false).includes(authorityCode);
}

// ---- 选择权限树节点：选中/取消指定权限树节点。
const authorityChoose = (data, checked, indeterminate) => {
  let authorityCode = data.authorityCode, index;
  if (checked) {
    // ---- 在当前节点被选中的同时选中父节点。该操作只需执行一级，因为更高层级的父节点会在一级
    // 父节点被选中后迭代调用当前方法选中。
    if ((index = authorityCode.lastIndexOf('/')) != -1) {
      authorityCode = authorityCode.substring(0, index);
      authorityTreeRef.value.setChecked(authorityCode, true, false);
    }
  } else {
    // ---- 在当前节点被取消选中的同时取消子节点。同样只执行一级，原因同上。注意！不同于一级父
    // 节点的唯一性，一级子节点是可能存在多个的。
    const data = authorityTreeRef.value.getNode(authorityCode);
    if (data && data.data && data.data.children && data.data.children.length > 0) {
      for (let child of data.data.children) {
        authorityTreeRef.value.setChecked(child.authorityCode, false, false);
      }
    }
  }
}

// ---- 角色插入/更新准备。
const roleCopy = ref(null);
const authorityTreeCopy = ref([])
const roleUpsertPrepare = () => {
  if (roleCode) {
    authorityTreeDisable(authorityTree.value, false);
    roleCopy.value = cloneDeep(role.value);
    authorityTreeCopy.value = cloneDeep(authorityTree.value);
  }
}

// ---- 角色插入/更新确认。
const roleUpsertFormRef = ref(null);
const roleUpsertFormRules = ref({
  "roleCode": [{ required: true, message: '请输入代码！', trigger: 'blur' }],
  "name": [{ required: true, message: '请输入名称！', trigger: 'blur' }]
});
const roleUpsertConfirm = () => {
  roleUpsertFormRef.value.validate((valid) => {
    if (valid) {
      roleUpsert.value.authorities = [];
      const authorityCodes = authorityTreeRef.value.getCheckedKeys(false);
      if (authorityCodes && authorityCodes.length > 0) {
        roleUpsert.value.authorities.push({ "authorityCode": APP_CODE, "expireDatetimeStr": null })
        for (let authorityCode of authorityTreeRef.value.getCheckedKeys(false)) {
          roleUpsert.value.authorities.push({
            "authorityCode": authorityCode,
            "expireDatetimeStr": authorityMap.value[authorityCode]
          });
        }
      }
      if (roleCode) {
        axios.post('/api/cms-web/role/update', roleUpsert.value).then(response => {
          if (response.data.success) {
            ElMessage.success('更新成功！');
            authorityTreeDisable(authorityTree.value, true);
            roleUpsertDisabled.value = true;
            roleCopy.value = null;
            authorityTreeCopy.value = null;
          } else {
            ElMessage.error(response.data.message);
          }
        });
      } else {
        axios.post('/api/cms-web/role/insert', roleUpsert.value).then(response => {
          if (response.data.success) {
            ElMessage.success('插入成功！');
            router.push('/home/role_list');
          } else {
            ElMessage.error(response.data.message);
          }
        });
      }
    }
  });
}
</script>

<template>
  <div class="role-upsert-page-div-class">
    <el-form ref="roleUpsertFormRef" :model="roleUpsert" :rules="roleUpsertFormRules" require-asterisk-position="right"
      style="width: 100%;">
      <!-- 角色信息 -->
      <div class="role-upsert-form-item-class">
        <el-form-item label="代码" prop="roleCode">
          <el-input v-model="roleUpsert.roleCode" style="width: 300px" disabled v-if="roleCode" />
          <el-input v-model="roleUpsert.roleCode" style="width: 300px" v-else>
            <template #prepend>{{ APP_CODE }}:</template>
          </el-input>
        </el-form-item>
        &nbsp; &nbsp; &nbsp;
        <el-form-item label="名称" prop="name">
          <el-input v-model="roleUpsert.name" style="width: 300px" />
        </el-form-item>
        &nbsp; &nbsp; &nbsp;
        <el-button type="primary" @click="roleUpsertConfirm()" v-if="roleCode">更新</el-button>
        <el-button type="primary" @click="roleUpsertConfirm()" v-else>插入</el-button>
      </div>
      <!-- 权限树 -->
      <div class="role-upsert-form-item-class">
        <el-tree ref="authorityTreeRef" :data="authorityTree" :props="authorityTreeProps" :expand-on-click-node="false"
          :check-on-click-node="true" :check-strictly="true" show-checkbox node-key="roleCode" default-expand-all
          @check-change="authorityChoose" style="width: 100%;">
          <template #default="{ node, data }">
            <div class="authority-tree-node-div-class" style="font-weight: bolder;"
              v-if="authorityIsCheck(data.roleCode)">
              [{{ data.authorityCode }}] - {{ data.name }}
              <el-date-picker v-model="authorityMap[data.roleCode]" size="small" type="datetime"
                format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
                :disabled="roleCode && roleUpsertDisabled" style="width: 170px" />
            </div>
            <div v-else>
              [{{ data.authorityCode }}] - {{ data.name }}
            </div>
          </template>
        </el-tree>
      </div>
    </el-form>
  </div>
</template>

<style scoped>
.role-upsert-page-div-class {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  width: 100%;
  height: 100%;
  padding: 20px 20px 20px 20px;
}

.role-upsert-form-item-class {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  width: 100%;

}

.authority-tree-node-div-class {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-end;
  width: 100%;
}
</style>
